package ccpvspiral1;

import repast.simphony.context.Context;
import repast.simphony.query.PropertyEquals;
import repast.simphony.render.RenderListener;
import repast.simphony.render.RendererListenerSupport;
import repast.simphony.visualization.*;
import repast.simphony.visualization.gis.DisplayGIS;


import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

import population.Population;

import coalition.CoalitionResults;
import coalition.CoalitionWithInfoInterface;

import com.sun.org.apache.xml.internal.security.encryption.ReferenceList;

//import BeansTestLib.default_package.testPanel;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author Nick Collier
 */
//
//implements IDisplay
public class CustomDisplay implements IDisplay{

	private final int MAX_DISJUNCTIVE_SIZE = 3;
	private String fileName = "C:/CCPV Data/kiran/malacca.csv";
	private RunTimeSettings rt = FileManager.importAgentLayer(fileName);
	//private ArrayList<ArrayList<Person>> population = Utilities.makePeople(rt);
	// represents what "tick" we are in the simulation... how many times we've stepped forward
	// note: this points to the next available empty storage slot as well
	private int tickCount = 0;

	//private CoalitionFrame coalitionFrame = new CoalitionFrame();
	private CCPVMainPanel coalitionPanel = new CCPVMainPanel();
	private population.PopulationInterface pop;
	int [] ascriptiveSpecs;
	private JPanel panel = new JPanel();
	private JLabel label = new JLabel();
	private Context context;
	private RendererListenerSupport support = new RendererListenerSupport();
	private boolean panelIsSetup = false;
	
	// RESULT STORAGE VARIABLES
	// Stores the results
	private CoalitionResults intResults = new CoalitionResults();
	private ArrayList<String> stringResults = new ArrayList<String>();
	private JFileChooser fileChooser = new JFileChooser();
	// this is the current location we're observing
	// starts at negative one b/c the intial state isn't observing anything until
	// the user presses the step forward button
	private int index = -1;


	/*
  public CustomDisplay(DisplayData data) {
    //this.context = context;
    super(data);
  }*/


	public CustomDisplay(Context context)
	{
		this.context = context;
	}


	/**
	 * Updates the state of the display to reflect whatever it is that it is displaying.
	 */
	public void update() {
	}

	/**
	 * Initializes the display. Called once before the display is made visible.
	 */
	public void init() {
		update();
	}

	/**
	 * Sets the Layout for the display to use.
	 *
	 * @param layout the layout to use
	 */
	public void setLayout(Layout layout) {
	}

	/**
	 * Sets the frequency of the layout.
	 *
	 * @param frequency the frequency of the layout
	 * @param interval  the interval if the frequency is AT_INTERVAL. The interval is in terms
	 *                  of number of calls to update()
	 */
	public void setLayoutFrequency(LayoutFrequency frequency, int interval) {
	}

	public void setupAscriptiveTree()
	{
		// setup ascriptiveCharList for testing purposes
		ArrayList2D refList = new ArrayList2D();
		for (int i = 0; i < rt.characteristics.size(); i++)
		{
			NamedArrayList<String> namedList = rt.characteristics.get(i);
			TaggedList category = new TaggedList(namedList.name);
			
			for (int j = 0; j < namedList.size(); j++)
			{
				category.add(namedList.get(j));
			}
			
			refList.add(category);
		}

		GisAgent.setClassAscriptiveChars(refList);

		ArrayList2D ascriptiveList = GisAgent.getAscriptiveCharsList();
		coalitionPanel.setAllAscriptiveTrees(rt.characteristics);
		
		/*
		DefaultMutableTreeNode root = (DefaultMutableTreeNode)coalitionPanel.getAscriptiveTree().getModel().getRoot();
		root.removeAllChildren();

		DefaultMutableTreeNode category = null;
		DefaultMutableTreeNode ascriptiveChar = null;

		for (int i = 0; i < ascriptiveList.size(); i++)
		{
			TaggedList currentAscriptive = ascriptiveList.get(i);
			category = new DefaultMutableTreeNode("" + currentAscriptive.getTag());

			for (int j = 0; j < currentAscriptive.size(); j++)
			{
				ascriptiveChar = new DefaultMutableTreeNode("" + currentAscriptive.get(j));
				category.add(ascriptiveChar);
			}

			root.add(category);
		}
		*/		

		//coalitionPanel.getAscriptiveTree().updateUI();
	}


	/**
	 * Gets a panel that contains the actual gui for visualization.
	 *
	 * @return a panel that contains the actual gui for visualization.
	 */
	public JPanel getPanel() {
		if (!panelIsSetup)
			setupCoalitionPanel();
		panel.add(coalitionPanel);
		return panel;
	}

	// sets all the button functionalities and the tree
	private void setupCoalitionPanel()
	{
		System.out.println(rt.toString());
		setupAscriptiveTree();
		// THIS IS TEMPORARILY SET TO {3, 3}
		ascriptiveSpecs = new int[2];  // EVIL EVIL EVIL MAGIC NUMBER 2!!!  // HEY, YOU TELL ME HOW TO GET THE RIGHT NUMBER!  :P
		ascriptiveSpecs[0] = rt.getNumChar(0);
		ascriptiveSpecs[1] = rt.getNumChar(1);
		//ascriptiveSpecs[2] = rt.getNumChar(2);

		pop = Population.getNewPopulationInterface(ascriptiveSpecs);
		pop.setMaximumDisjunctiveSize(MAX_DISJUNCTIVE_SIZE);
		
		JButton loadButton = coalitionPanel.getLoadDataButton();
		loadButton.addActionListener(new java.awt.event.ActionListener()
		{
			public void actionPerformed(java.awt.event.ActionEvent evt) 
			{	
				int fileVal = fileChooser.showOpenDialog(coalitionPanel);
				if (fileVal == JFileChooser.APPROVE_OPTION)
				{
					// TODO: may be fixed... check loading
					fileName = fileChooser.getSelectedFile().getAbsolutePath();
					System.out.println(fileName);
					rt = FileManager.importAgentLayer(fileName);
					//population = Utilities.makePeople(rt);
					setupAscriptiveTree();
					pop = Population.getNewPopulationInterface(ascriptiveSpecs);
					pop.setMaximumDisjunctiveSize(MAX_DISJUNCTIVE_SIZE);
					tickCount = 0;
					coalitionPanel.coalitionTextPane.setText("NEW DATA LOADED");
					intResults = new CoalitionResults();
					stringResults = new ArrayList<String>();
					DefaultMutableTreeNode resultsRoot = (DefaultMutableTreeNode)coalitionPanel.coalitionTree.getModel().getRoot();
					resultsRoot.removeAllChildren();
					coalitionPanel.coalitionTree.updateUI();
				}
				else
				{
					System.out.println("error in loading data: approve option not met.");
				}
			}
		});
		
		JButton backButton = coalitionPanel.previousYearButton;
		backButton.setEnabled(false);
		backButton.addActionListener(new java.awt.event.ActionListener()
		{
			public void actionPerformed(java.awt.event.ActionEvent evt) 
			{	
				if (index > 0)
				{
					index--;
					// if we've pressed the back button and we're here that means we're at the same place we
					// were when we hit the forward button earlier.  so go back one more step.
					if (index == intResults.coalitions.size() - 1)
						index--;
					coalitionPanel.coalitionTextPane.setText(stringResults.get(index));
					setResultsTree(index);
					setResultsTitle(index + rt.getFirstYear());
					//System.out.println("this is the tick count at back button AFTER --: " + index);
					
					if (index == 0)
						coalitionPanel.previousYearButton.setEnabled(false);
				}
			}
		});

		JButton stepForwardButton = coalitionPanel.nextYearButton;
		stepForwardButton.addActionListener(new java.awt.event.ActionListener() 
		{
			
			public void actionPerformed(java.awt.event.ActionEvent evt) 
			{	
				coalitionPanel.previousYearButton.setEnabled(true);
				if ((tickCount >= intResults.coalitions.size()) && (index >= intResults.coalitions.size()-1))
				{
					// Since the current empty storage slot is the tickCount and the tickCount slot
					// is about to get filled, the index must be set to the current tickCount
					index = tickCount;
					//Utilities.updateAgentPopulation(rt, population, rt.getFirstYear()+tickCount);
					System.out.println("Ready to calculate coalition.");
/*
					// Register the agents
					int testSize = 0;
					for (int i = 0; i < population.size(); i++)
					{
						System.out.println("Processing Bucket: " + i + " ("+ population.get(i).size()+")");
						ArrayList<Person> bucket = population.get(i);
						// set the power for this bucket
						if (bucket.size() > 0)
							pop.setSectorPower(bucket.get(0).getCharacterInts(), (float)rt.getEpoch(tickCount).getLinearValueAt(rt.getFirstYear()+tickCount, 0));

						for (int j = 0; j < bucket.size(); j++)
						{
							int[] agent = bucket.get(j).getCharacterInts();
							pop.registerAgentInSector(agent);
							testSize++;
						}
					}
					*/
					//System.out.println("testSize: " + testSize);
					System.out.println("total power: " + pop.getTotalModulatedSize());

						
					CoalitionWithInfoInterface coal = pop.getWinningCoalition();
					List<int[]> coalList = coal.getCoalition().getSectorsInvolved();

//					String coalPrint = CoalitionPrint.getCoalitionPrintStringWithComplements(coalList, GisAgent.getAscriptiveCharsList(), pop, rt.getFirstYear()+tickCount);
					String coalPrint = "disabled due to code upgrade";
					coalitionPanel.coalitionTextPane.setText(coalPrint);
					// update the storage of old coalitions
					//intResults.popInterfaces.add(pop);
					intResults.coalitions.add(coalList);
					setResultsTree(tickCount);
					stringResults.add(coalPrint);
					setResultsTitle(tickCount + rt.getFirstYear());
					
					pop = Population.getNewPopulationInterface(ascriptiveSpecs);
					pop.setMaximumDisjunctiveSize(MAX_DISJUNCTIVE_SIZE);
					tickCount++;
					//System.out.println("this is the tick count at if statement AFTER ++: " + tickCount);
				}
				else
				{
					//System.out.println("this is the tick count at else statement BEFORE ++: " + index);
					index++;
					
					coalitionPanel.coalitionTextPane.setText(stringResults.get(index));
					setResultsTree(index);
					setResultsTitle(index + rt.getFirstYear());
					pop = Population.getNewPopulationInterface(ascriptiveSpecs);
					pop.setMaximumDisjunctiveSize(MAX_DISJUNCTIVE_SIZE);
				}
			}
		});

		panelIsSetup = true;
	}

	// sets the result tree of the coalitionPanel based on the stored coalitions
	private void setResultsTree(int resultIndex)
	{
		DefaultMutableTreeNode root = (DefaultMutableTreeNode)coalitionPanel.coalitionTree.getModel().getRoot();
		root.removeAllChildren();
		
		List<int[]> coals = intResults.coalitions.get(resultIndex);
		ArrayList<ArrayList<Integer>> representedAscriptives = new ArrayList<ArrayList<Integer>>();
		
		// setup the above arraylist
		for (int i = 0; i < ascriptiveSpecs.length; i++)
		{
			representedAscriptives.add(new ArrayList<Integer>());
		}
		
		// check which ascriptives are present
		for (int i = 0; i < coals.size(); i++)
		{
			int[] currentCoal = coals.get(i);
			
			for (int j = 0; j < currentCoal.length; j++)
			{
				ArrayList<Integer> currentAscriptiveCat = representedAscriptives.get(j);
				
				if (!contains(currentAscriptiveCat, currentCoal[j]))
					currentAscriptiveCat.add(currentCoal[j]);
			}
		}
		
		// set tree up for each category of ascriptive characteristic	
		DefaultMutableTreeNode category = null;
		DefaultMutableTreeNode ascriptiveChar = null;
		for (int i = 0; i < representedAscriptives.size(); i++)
		{
			category = new DefaultMutableTreeNode(GisAgent.getAscriptiveCharsList().get(i).getTag());
			ArrayList<Integer> currentCat = representedAscriptives.get(i);
			
			for (int j = 0; j < currentCat.size(); j++)
			{
				ascriptiveChar = new DefaultMutableTreeNode(GisAgent.getAscriptiveCharsList().get(i).get(currentCat.get(j)));
				category.add(ascriptiveChar);
			}
			
			root.add(category);
		}
		
		coalitionPanel.coalitionTree.updateUI();
	}
	
	private boolean contains(ArrayList<Integer> list, int x)
	{
		boolean ret = false;
		
		for (int i = 0; i < list.size(); i++)
		{
			if (list.get(i).intValue() == x)
				return true;
		}
		
		return ret;
	}
	
	private void setResultsTitle(int year)
	{
		coalitionPanel.dataFileNameLabel.setText(fileName + ": " + year);
	}
	
	/**
	 * Destroys the display, allowing it to free any resources it may have acquired.
	 */
	public void destroy() {
	}

	/**
	 * Notifies this IDisplay that its associated gui widget has been iconified.
	 */
	public void iconified() {
	}

	/**
	 * Notifies this IDisplay that its associated gui widget has been deIconified.
	 */
	public void deIconified() {
	}

	/**
	 * Notifies this IDisplay that its associated gui widget has been closed.
	 */
	public void closed() {
	}

	/**
	 * Adds a probe listener to listen for probe events produced by this IDisplay.
	 *
	 * @param listener the listener to add
	 */
	public void addProbeListener(ProbeListener listener) {
	}

	/**
	 * Gets the layout the display uses
	 *
	 * @return a layout object
	 */
	public Layout getLayout() {
		return null;
	}

	public DisplayEditorLifecycle createEditor(JPanel panel) {
		return null;
	}

	public void render() {
		label.setText("oogy boogy Count: " + 55);
		support.fireRenderFinished(this);
	}

	public void addRenderListener(RenderListener listener) {
		support.addListener(listener);
	}

	public void setPause(boolean pause) {
	}


	public void resetHomeView() {
	}

	public void registerToolBar(JToolBar bar) {
	}

	public void addDisplayListener(DisplayListener listener) {
	}
}
